#ifndef HAPTREE
#define HAPTREE

#include<stdlib.h>
#include<stdio.h>
#include<strings.h>
#include<string.h>
#include<math.h>

typedef struct{
  unsigned int start;
  unsigned int length;
  unsigned int multiplicity;
  unsigned int refCount;
  int *alleles;
} PartialRead;

typedef struct ReadEvidence{
  unsigned int multiplicity;
  double pWeight;
  PartialRead *pRead;
  struct ReadEvidence * next;
} ReadEvidence;

typedef struct ReadEvidenceList{
  ReadEvidence *rEvidence;
  unsigned int offset;
  struct ReadEvidenceList * next;
} ReadEvidenceList;

typedef struct HapNode{
  unsigned int nChildren;
  struct HapNode *children;
  struct HapNode *prev_sibling;
  struct HapNode *next_sibling;
  struct HapNode *next;
  struct HapNode *parent;
  ReadEvidenceList * evidenceList;
  unsigned int allele;
  double totalProb;
} HapNode;

typedef struct{
  unsigned int nAlleles;
  unsigned int totalNodes;
  HapNode * allNodes;
  HapNode **alleleIndex;
} Locus;

typedef struct{
  unsigned int totalLoci;
  unsigned int currentLoci;
  Locus **loci;
  ReadEvidence evidenceCollection;
  unsigned int N;
} HaplotypeCollection;

typedef struct Parameters{
  double delta;
  double omega;
  double significanceCutOff;
}Parameters;


/* Evidence manipulations */
ReadEvidenceList *allocNewEvidence(ReadEvidence *rEvidence);
void addNodeEvidence(HapNode * node, ReadEvidenceList* nodeEvidence);
void extendIncompleteEvidence(HaplotypeCollection * hapCol);
HapNode * matchNextLocus(HapNode *node, unsigned int allele);
unsigned int matchPath(HapNode *node, ReadEvidenceList *nodeEvidence);


/* PartialRead manipulations */
ReadEvidence *createEvidence(HaplotypeCollection *hapCol, PartialRead * read);
int addRead(HaplotypeCollection *hapCol, PartialRead * read);
int removeRead(HaplotypeCollection *hapCol, PartialRead *read);
PartialRead *copyRead(PartialRead *pRead);
void freeRead(PartialRead *pRead);


/* Locus */
Locus *allocateLocus(unsigned int length, unsigned int nAlleles);
void freeLocus(Locus *locus);

Locus * addLocus(Locus * root, unsigned int nAlleles);
void linkNextLocus(Locus *lastLocus, Locus *newLocus);
void extendHaplotypes(HaplotypeCollection *hapCol, unsigned int nAlleles);

/* frequencies manipulations */
void pruneHaplotypes(HaplotypeCollection *hapCol, double significance);
void setHaplotypeFreqs(HaplotypeCollection *hapCol, double *freqs);
void computeInternalProbs(HaplotypeCollection *hapCol);
double computeCollectionFreqs(HaplotypeCollection *hapCol, Parameters *pars, double * freqs);
void computeUpdatedProbs(HaplotypeCollection *hapCol);

void deleteHaplotype(HaplotypeCollection *hapCol, HapNode *node, HapNode *prevNode, unsigned int locus);
void rebuildAlleleIndex(HaplotypeCollection *hapCol);

void printCollection(HaplotypeCollection *hapCol);
void printHaplotype(HapNode * hap, unsigned int locus, unsigned int skip);

/* HaplotypeCollection */
HaplotypeCollection *createHaplotypeCollection(unsigned int nLoci);
void destroyHaplotypeCollection(HaplotypeCollection *hapCol);
void destroyEvidence(ReadEvidence *evidence);
double getListHaplotype(HaplotypeCollection *hapCol, 
			HapNode *node, unsigned int *haplotype);

/* HapNode */
HapNode *newHapNode(unsigned int allele);
void freeHapNode(HapNode * hapNode);

/* other methods */


#endif 
